//
//  SleepChartVC.swift
//  TimeBoat
//
//  Created by bo wang on 2022/8/26.
//  Copyright © 2022 Time Boat. All rights reserved.
//

import UIKit
import Charts

class SleepChartVC: StepsChartVC {
    
    @IBOutlet var soberLabel: UILabel!
    @IBOutlet var soberTitleLabel: UILabel!
    
    @IBOutlet var lightSleepLabel: UILabel!
    @IBOutlet var lightSleepTitleLabel: UILabel!
    
    @IBOutlet var deepSleepLabel: UILabel!
    @IBOutlet var deepSleepTitleLabel: UILabel!
    
    @IBOutlet var sleepSummaryTitleLabel: UILabel!
    @IBOutlet var sleepSummaryLabel: UILabel!
    
    override func loadChartView() {
        super.loadChartView()
        
        if case .day = granularitie {
            chartView?.xAxis.axisMinimum = -6 // -6是指18:00
            chartView?.xAxis.axisMaximum = 10 // 10是10:00
        }
    }
    
    override func loadDayData(_ date: Date) {
        API.getSleepDailyData(date.dayStart, imei: imei) { [weak self] result in
            guard result.suc else {
                self?.onLoadDataFailed(result.errDesc)
                return
            }
            // 这个接口在没有数据时不返回 data 字段
            let list = result.data?.list ?? []
            let info = result.data?.info ?? ChartSummaryInfoModel()
            self?.onLoadSummaryData(info)

            let entryGroups = list.compactMap { unit -> [ChartDataEntry]? in
                guard let start = unit.start, let end = unit.end else { return nil }
                return [
                    ChartDataEntry(x: start, y: unit.duration, data: unit),
                    ChartDataEntry(x: end, y: unit.duration, data: unit)
                ]
            }
            guard !entryGroups.isEmpty else {
                self?.reloadChartView(data: nil)
                return
            }
            
            let sets = entryGroups.enumerated().map { ele -> NormalLineChartDataSet in
                let dataset = NormalLineChartDataSet(entries: ele.element, label: "\(ele.offset)")
                dataset.mode = .stepped
                dataset.lineWidth = 0
                if let unit = ele.element.first!.data as? SleepDailyDataUnit {
                    switch unit.sleepState {
                    case 0: dataset.fill = ColorFill(color: HEX(0xF3C27F)!)
                    case 1: dataset.fill = ColorFill(color: HEX(0x9FA6FF)!)
                    case 2: dataset.fill = ColorFill(color: HEX(0x4A6CFD)!)
                    default: dataset.fill = ColorFill(color: HEX(0xF5F2ED)!)
                    }
                }
                return dataset
            }
            self?.reloadChartView(data: LineChartData(dataSets: sets))
        }
    }
    
    override func didLoadDayData(_ entries: [ChartDataEntry]) {
        guard !entries.isEmpty else {
            reloadChartView(data: nil)
            return
        }
        let dataSet = NormalLineChartDataSet(entries: entries)
        if entries.count == 1 {
            // 只有一个数据的时候显示圆圈
            dataSet.setupShowCircleDot()
        }
        dataSet.mode = .stepped
        reloadChartView(data: LineChartData(dataSet: dataSet))
    }
    
    override func loadWeekData(_ date: Date) {
        API.getSleepData(date, .week, imei: imei) { [weak self] result in
            guard result.suc, let data = result.data else {
                self?.onLoadDataFailed(result.errDesc)
                return
            }
            self?.onLoadSummaryData(data.info)
            
            let entries = data.list.compactMap { unit -> BarChartDataEntry? in
                guard let weekday = unit.weekday else { return nil }
                return BarChartDataEntry(x: Double(weekday), y: Double(unit.totalMinute), data: unit)
            }
            self?.didLoadWeekData(entries)
        }
    }
    
    override func loadMonthData(_ date: Date) {
        API.getSleepData(date, .month, imei: imei) { [weak self] result in
            guard result.suc, let data = result.data else {
                self?.onLoadDataFailed(result.errDesc)
                return
            }
            self?.onLoadSummaryData(data.info)
            
            let entries = data.list.compactMap { unit -> ChartDataEntry? in
                guard let day = unit.day else { return nil }
                return ChartDataEntry(x: Double(day), y: Double(unit.totalMinute), data: unit)
            }
            self?.didLoadMonthData(entries)
        }
    }
    
    override func loadYearData(_ date: Date) {
        API.getSleepYearlyData(date, imei: imei) { [weak self] result in
            guard result.suc, let data = result.data else {
                self?.onLoadDataFailed(result.errDesc)
                return
            }
            self?.onLoadSummaryData(data.info)
            
            let entries = data.list.compactMap { unit -> BarChartDataEntry? in
                guard unit.month > 0 else { return nil }
                return BarChartDataEntry(x: Double(unit.month), y: Double(unit.totalMinute), data: unit)
            }
            self?.didLoadYearData(entries)
        }
    }

    override func onLoadSummaryData(_ info: ChartSummaryInfoModel?) {
        guard let info = info else { return }
        
        let hmstr: (Double) -> String = { time in
            let h = Int(time / 60)
            let m = Int(time) % 60
            if h > 0, m > 0 {
                return "\(h)H\(m)M"
            } else if h > 0 {
                return "\(h)H"
            } else {
                return "\(m)M"
            }
        }
        
        if case .day = granularitie {
            sleepSummaryTitleLabel.text = "睡眠时长"
            
            soberLabel.text = hmstr(info.totalSoberMinute)
            lightSleepLabel.text = hmstr(info.totalLightSleepMinute)
            deepSleepLabel.text = hmstr(info.totalDeepSleepMinute)
            sleepSummaryLabel?.text = hmstr(info.totalMinute)
            return
        }
        
        soberTitleLabel.text = "平均清醒"
        lightSleepTitleLabel.text = "平均浅睡"
        deepSleepTitleLabel.text = "平均深睡"
        sleepSummaryTitleLabel.text = "平均睡眠时长"
        
        soberLabel.text = hmstr(info.averageSoberMinute)
        lightSleepLabel.text = hmstr(info.averageLightSleepMinute)
        deepSleepLabel.text = hmstr(info.averageDeepSleepMinute)
        
        sleepSummaryLabel?.text = hmstr(info.averageSoberMinute + info.averageLightSleepMinute + info.averageDeepSleepMinute)
    }
}
